/* File contains the code for writing thread of beacon node... */

#include "projectHeader.h"

void * beaconWrite(void * t)
{
//	printf("\nINSIDE BEACON Write...\n");
	int socketDesc = (int)t;


	pthread_mutex_lock(&sockIndexMapMutex);
	int index=sockFDToQIndexMap[socketDesc];
//	printf("\nINSIDE BEACON Write: INDEX is : %d\n",index);
	pthread_mutex_unlock(&sockIndexMapMutex);
	/*********************************************************************
	*
	*	Code for dispatcher thread here.
	*	Read from write queue and write it to the socket..	
	*
	**********************************************************************/
	queueItem itemFromQueue;
	while(1)
	{
		//Wait for Item in Queue. Deque item and process it.
		pthread_mutex_lock(&wrtieQMutex[index]);	
		while ((int)wrtieThreadQueue[index].size() == 0) 
		{
			
			pthread_cond_wait(&wrtieQCV[index], &wrtieQMutex[index]);

		}
//		printf("\nINSIDE BEACON Write: Socket descriptor is : %d\n",socketDesc);
			itemFromQueue=wrtieThreadQueue[index].front();
			wrtieThreadQueue[index].pop_front();

		pthread_mutex_unlock(&wrtieQMutex[index]);
		

		
		// if send message is store message
		// {
		//		read the file from the disk
		//		send entire file over the network
		// }
		// else
		//		code written below for sending


		

		//Send the msg. to corrsponding node.
		//Sending the header of the node.

			int ret=0;
				if(itemFromQueue.msgHeader.messageType!=0xF8)
			//printf("MessageType is %x in write of %d.\n",itemFromQueue.msgHeader.messageType,socketDesc);
			if ((ret=(send(socketDesc,&(itemFromQueue.msgHeader),sizeof(msgHeaderClass), 0))) == -1)
			{
				//printf("ERROR: error in sending  Header from write thread.\n ");

				pthread_exit(NULL);
			}
			//printf("SEND RETURN IS %d\n",ret);
			//printf("DATABUF is %s",itemFromQueue.dataBuf);
			if(itemFromQueue.msgHeader.messageType==0xCC)
			{
		//		printf("---------WRITE QUEUE: header is :\n");
		/*		printf("r STRS %d 0x%02x %x%x%x%x %x\n",
								(itemFromQueue.msgHeader.msgDataLength+27),
								(unsigned char)itemFromQueue.msgHeader.ttlInHeader,
								(unsigned char)itemFromQueue.msgHeader.UOID[16],
								(unsigned char)itemFromQueue.msgHeader.UOID[17],
								(unsigned char)itemFromQueue.msgHeader.UOID[18],
								(unsigned char)itemFromQueue.msgHeader.UOID[19],
								(unsigned char)itemFromQueue.dataBuf[0]);

			*/
				char newNumMetaFile[256];
				char newNumDataFile[256];
				memset(&newNumMetaFile[0],'\0',256);
				memset(&newNumDataFile[0],'\0',256);
				char isTempFlag = '\0';  
				if(itemFromQueue.msgHeader.msgDataLength<MAXFILEBUF) // replace with if filesize + metadatasize + 4 is less than maxbuffsize. 
				{
					char appendDFileName[256];
					char appendMFileName[256];
					memset(&appendMFileName[0],'\0',256);
					memset(&appendDFileName[0],'\0',256);
					isTempFlag = itemFromQueue.dataBuf[2];
					int numfileId=itemFromQueue.dataBuf[0];

					sprintf(appendDFileName, "/%d.data", numfileId);
					sprintf(appendMFileName, "/%d.meta", numfileId);

					memcpy(newNumMetaFile,homeDir,strlen(homeDir));
					if(isTempFlag == '0')
					{
						strcat(newNumMetaFile,"/files");
					}
					else
					{
						//strcat(newNumMetaFile,"/temp");
					}
					strcat(newNumMetaFile,appendMFileName);

					memcpy(newNumDataFile,homeDir,strlen(homeDir));
					if(isTempFlag == '0')
					{
						strcat(newNumDataFile,"/files");
					}
					else
					{
						//strcat(newNumDataFile,"/temp");
					}
					strcat(newNumDataFile,appendDFileName);
		//			printf("3-------------------%s--------%s\n",newNumMetaFile,newNumDataFile);
					
					struct stat statistics;
					int status;
					status = stat((char*)newNumDataFile,&statistics);
					if(status<0)
					{
						//printf("WRITE THREAD: File does not exist.\n");
					}
					unsigned int filesize = statistics.st_size;
					
					struct stat statistics1;
					int status1;
					status1 = stat((char*)newNumMetaFile,&statistics1);
					if(status1<0)
					{
						//printf("WRITE THREAD: File does not exist.\n");
					}
					unsigned int metaFileSize = statistics1.st_size;
		//			printf("WRITE THREAD: Size of file %s is %u.\n",newNumMetaFile,metaFileSize);
					//memcpy(&itemFromQueue.dataBuf[0],&metaFileSize,sizeof(metaFileSize));
					
					
					FILE *numDataFile = fopen(newNumDataFile, "r");
					//FILE *sfile = fopen(storeFileName, "r");
					
					
					char copyBuf[MAXFILEBUF];
					memset(&copyBuf[0],'\0',MAXFILEBUF);
					memcpy(&copyBuf[0],&metaFileSize,sizeof(metaFileSize));
					
					/************************************************
					*	Creating metaFile packet and sending		*
					************************************************/

					// Write the numeric meta file.

					FILE *numMetaFile = fopen(newNumMetaFile, "r");
					
					if (fread((copyBuf+4),1,metaFileSize,numMetaFile) < 0)
					{
						//printf("Error in reading meta file\n");
					}

					fclose(numMetaFile);
					if (fread((copyBuf+metaFileSize + 4),1,filesize,numDataFile) < 0)
					{
						//printf("Error in reading store file\n");
					}
					//send file metadata.
					if (send(socketDesc,&(copyBuf),itemFromQueue.msgHeader.msgDataLength, 0) == -1)
					{
						//printf("ERROR: error in sending  Data. from write Thread.\n\n");
						pthread_exit(NULL);
					}



				}
				else
				{
				
					/*
						27-30	Metadata Length		Length of the Metadata field.
						31+		Metadata			File Metadata.
						(?)+	File Data			The actual file. A node receiving this message must compute the 
													SHA1 hash value of the file and compare it against the stored file description.
													If it does not match, the file should be discarded.
					*/
					//memcpy(&dataBuf[0],);
					char appendDFileName[256];
					char appendMFileName[256];
					memset(&appendMFileName[0],'\0',256);
					memset(&appendDFileName[0],'\0',256);
					
					isTempFlag = itemFromQueue.dataBuf[2];
					int numfileId=itemFromQueue.dataBuf[0];

					sprintf(appendDFileName, "/%d.data", numfileId);
					sprintf(appendMFileName, "/%d.meta", numfileId);

					memcpy(newNumMetaFile,homeDir,strlen(homeDir));
					if(isTempFlag == '0')
					{
						strcat(newNumMetaFile,"/files");
					}
					else
					{
						//strcat(newNumMetaFile,"/temp");
					}
					strcat(newNumMetaFile,appendMFileName);

					memcpy(newNumDataFile,homeDir,strlen(homeDir));

					if(isTempFlag == '0')
					{
						strcat(newNumDataFile,"/files");
					}
					else
					{
						//strcat(newNumDataFile,"/temp");
					}
					strcat(newNumDataFile,appendDFileName);
			//		printf("3-------------------%s--------%s\n",newNumMetaFile,newNumDataFile);
					
					struct stat statistics;
					int status;
					status = stat((char*)newNumDataFile,&statistics);
					if(status<0)
					{
						//printf("WRITE THREAD: File does not exist.\n");
					}
					unsigned int filesize = statistics.st_size;
					
					struct stat statistics1;
					int status1;
					status1 = stat((char*)newNumMetaFile,&statistics1);
					if(status1<0)
					{
						//printf("WRITE THREAD: File does not exist.\n");
					}
					unsigned int metaFileSize = statistics1.st_size;
			//		printf("WRITE THREAD: Size of file %s is %u.\n",newNumMetaFile,metaFileSize);
					//memcpy(&itemFromQueue.dataBuf[0],&metaFileSize,sizeof(metaFileSize));
					
					
					FILE *numDataFile = fopen(newNumDataFile, "r");
					//FILE *sfile = fopen(storeFileName, "r");
					
					
					char copyBuf[MAXFILEBUF];
					memset(&copyBuf[0],'\0',MAXFILEBUF);
					memcpy(&copyBuf[0],&metaFileSize,4);
			//		printf("MetaLength is %02X%02X%02X%02X\n",copyBuf[0],copyBuf[1],copyBuf[2],copyBuf[3]);
					/************************************************
					*	Creating metaFile packet and sending		*
					************************************************/

					// Write the numeric meta file.

					FILE *numMetaFile = fopen(newNumMetaFile, "r");
					
					if (fread((copyBuf+4),1,metaFileSize,numMetaFile) < 0)
					{
						//printf("Error in reading meta file\n");
					}
		//				printf("Meta Read \n%s\n\n\n\n",copyBuf);

					fclose(numMetaFile);


					/*****************************************************************/

					int sendMetaDataPacketLength =  metaFileSize + 4;
					filesize = filesize - sendMetaDataPacketLength;
					int intitalDataToBeSent = MAXFILEBUF - sendMetaDataPacketLength;
					if (fread((copyBuf+metaFileSize+4),1,intitalDataToBeSent,numDataFile) < 0)
					{
						//printf("Error in reading store file\n");
					}
					//send file metadata.
					int sendByte=0;
					if ((sendByte=send(socketDesc,&(copyBuf),MAXFILEBUF, 0)) == -1)
					{
						//printf("ERROR: error in sending  Data. from write Thread.\n\n");
						pthread_exit(NULL);
					}

					//printf("Data Read\n%s\n\n\n\n",copyBuf);
					//sending entire file.
					
					int numberOfSegments = ceil((double)filesize/MAXFILEBUF);	
			//		printf("BYTES SENT : %d\n",sendByte);
			//		printf("WRITE THREAD: Number of Segments is %d\n",numberOfSegments);
					int dataleft=filesize;
					if(dataleft<0)
					{
					}
					int remainingDataToBeCopied = filesize;
					// char copyBuf[MAXFILEBUF];
					 memset(&copyBuf[0],'\0',MAXFILEBUF);
					for(int k=0;k<numberOfSegments;k++)
					{
						int bytestoread;
						if (remainingDataToBeCopied > MAXFILEBUF)
						{
							bytestoread = MAXFILEBUF;
							remainingDataToBeCopied = remainingDataToBeCopied - MAXFILEBUF;
						}
						else
							bytestoread = remainingDataToBeCopied;

						memset(&copyBuf[0],'\0',MAXFILEBUF);
						if (fread(copyBuf,1,bytestoread,numDataFile) < 0)
						{
							//printf("Error in reading store file\n");
						}
						//fwrite(copyBuf, 1, bytestoread, numDataFile);	
						
						//send file data.

						////printf("%s\n\n\n\n",copyBuf);
						 memset(&copyBuf[0],'\0',MAXFILEBUF);
						if (send(socketDesc,copyBuf,bytestoread, 0) == -1)
						{
							//printf("ERROR: error in sending  Data. from write Thread.\n\n");
							pthread_exit(NULL);
						}
						//sleep(1);
					}
			//		printf("WRITE THREAD: FILE SENT\n");
					fclose(numDataFile);
					//fclose(sfile);

				}
			}
//=============================================================GET RESP START=========================
			else if(itemFromQueue.msgHeader.messageType==0xDB)
			{
	//			printf("---------WRITE QUEUE: header is :\n");
	/*			printf("r STRS %d 0x%02x %x%x%x%x %x\n",
								(itemFromQueue.msgHeader.msgDataLength+27),
								(unsigned char)itemFromQueue.msgHeader.ttlInHeader,
								(unsigned char)itemFromQueue.msgHeader.UOID[16],
								(unsigned char)itemFromQueue.msgHeader.UOID[17],
								(unsigned char)itemFromQueue.msgHeader.UOID[18],
								(unsigned char)itemFromQueue.msgHeader.UOID[19],
								(unsigned char)itemFromQueue.dataBuf[0]);*/
				char newNumMetaFile[256];
				char newNumDataFile[256];
				memset(&newNumMetaFile[0],'\0',256);
				memset(&newNumDataFile[0],'\0',256);
				char isTempFlag = '\0';  
				if(itemFromQueue.msgHeader.msgDataLength<MAXFILEBUF) // replace with if filesize + metadatasize + 4 is less than maxbuffsize. 
				{
					char appendDFileName[256];
					char appendMFileName[256];
					memset(&appendMFileName[0],'\0',256);
					memset(&appendDFileName[0],'\0',256);
					isTempFlag = itemFromQueue.dataBuf[22];
					int numfileId=itemFromQueue.dataBuf[20];

					sprintf(appendDFileName, "/%d.data", numfileId);
					sprintf(appendMFileName, "/%d.meta", numfileId);

					memcpy(newNumMetaFile,homeDir,strlen(homeDir));
					if(isTempFlag == '0')
					{
						strcat(newNumMetaFile,"/files");
					}
					else
					{
						//strcat(newNumMetaFile,"/temp");
					}
					strcat(newNumMetaFile,appendMFileName);

					memcpy(newNumDataFile,homeDir,strlen(homeDir));
					if(isTempFlag == '0')
					{
						strcat(newNumDataFile,"/files");
					}
					else
					{
						//strcat(newNumDataFile,"/temp");
					}
					strcat(newNumDataFile,appendDFileName);
	//				printf("3-------------------%s--------%s\n",newNumMetaFile,newNumDataFile);
					
					struct stat statistics;
					int status;
					status = stat((char*)newNumDataFile,&statistics);
					if(status<0)
					{
						//printf("WRITE THREAD: File does not exist.\n");
					}
					unsigned int filesize = statistics.st_size;
					
					struct stat statistics1;
					int status1;
					status1 = stat((char*)newNumMetaFile,&statistics1);
					if(status1<0)
					{
						//printf("WRITE THREAD: File does not exist.\n");
					}
					unsigned int metaFileSize = statistics1.st_size;
	//				printf("WRITE THREAD: Size of file %s is %u.\n",newNumMetaFile,metaFileSize);
					//memcpy(&itemFromQueue.dataBuf[0],&metaFileSize,sizeof(metaFileSize));
					
					
					FILE *numDataFile = fopen(newNumDataFile, "r");
					//FILE *sfile = fopen(storeFileName, "r");
					
					
					char copyBuf[MAXFILEBUF];
					memset(&copyBuf[0],'\0',MAXFILEBUF);
					memcpy(&copyBuf[0],&itemFromQueue.dataBuf[0],20);
					memcpy(&copyBuf[20],&metaFileSize,4);
					
					/************************************************
					*	Creating metaFile packet and sending		*
					************************************************/

					// Write the numeric meta file.

					FILE *numMetaFile = fopen(newNumMetaFile, "r");
					
					if (fread((copyBuf+24),1,metaFileSize,numMetaFile) < 0)
					{
						//printf("Error in reading meta file\n");
					}

					fclose(numMetaFile);
					if (fread((copyBuf+metaFileSize + 24),1,filesize,numDataFile) < 0)
					{
						//printf("Error in reading store file\n");
					}
					fclose(numDataFile);
	//				printf("Copy Buffer is %s and Size is %d",copyBuf,(int)strlen(copyBuf));
					//send file metadata.
					if (send(socketDesc,&(copyBuf),itemFromQueue.msgHeader.msgDataLength, 0) == -1)
					{
						//printf("ERROR: error in sending  Data. from write Thread.\n\n");
						pthread_exit(NULL);
					}
					


				}
				else
				{
				
					/*
						27-30	Metadata Length		Length of the Metadata field.
						31+		Metadata			File Metadata.
						(?)+	File Data			The actual file. A node receiving this message must compute the 
													SHA1 hash value of the file and compare it against the stored file description.
													If it does not match, the file should be discarded.
					*/
					//memcpy(&dataBuf[0],);
					char appendDFileName[256];
					char appendMFileName[256];
					memset(&appendMFileName[0],'\0',256);
					memset(&appendDFileName[0],'\0',256);
					
					isTempFlag = itemFromQueue.dataBuf[22];
					int numfileId=itemFromQueue.dataBuf[20];

					sprintf(appendDFileName, "/%d.data", numfileId);
					sprintf(appendMFileName, "/%d.meta", numfileId);

					memcpy(newNumMetaFile,homeDir,strlen(homeDir));
					if(isTempFlag == '0')
					{
						strcat(newNumMetaFile,"/files");
					}
					else
					{
						//strcat(newNumMetaFile,"/temp");
					}
					strcat(newNumMetaFile,appendMFileName);

					memcpy(newNumDataFile,homeDir,strlen(homeDir));

					if(isTempFlag == '0')
					{
						strcat(newNumDataFile,"/files");
					}
					else
					{
						//strcat(newNumDataFile,"/temp");
					}
					strcat(newNumDataFile,appendDFileName);
		//			printf("3-------------------%s--------%s\n",newNumMetaFile,newNumDataFile);
					
					struct stat statistics;
					int status;
					status = stat((char*)newNumDataFile,&statistics);
					if(status<0)
					{
						//printf("WRITE THREAD: File does not exist.\n");
					}
					unsigned int filesize = statistics.st_size;
					
					struct stat statistics1;
					int status1;
					status1 = stat((char*)newNumMetaFile,&statistics1);
					if(status1<0)
					{
						//printf("WRITE THREAD: File does not exist.\n");
					}
					unsigned int metaFileSize = statistics1.st_size;
	//				printf("WRITE THREAD: Size of file %s is %u.\n",newNumMetaFile,metaFileSize);
					//memcpy(&itemFromQueue.dataBuf[0],&metaFileSize,sizeof(metaFileSize));
					
					
					FILE *numDataFile = fopen(newNumDataFile, "r");
					//FILE *sfile = fopen(storeFileName, "r");
					
					
					char copyBuf[MAXFILEBUF];
					memset(&copyBuf[0],'\0',MAXFILEBUF);
					memcpy(&copyBuf[0],&itemFromQueue.dataBuf[0],20);
					memcpy(&copyBuf[20],&metaFileSize,4);
					//printf("MetaLength is %02X%02X%02X%02X\n",copyBuf[0],copyBuf[1],copyBuf[2],copyBuf[3]);
					/************************************************
					*	Creating metaFile packet and sending		*
					************************************************/

					// Write the numeric meta file.

					FILE *numMetaFile = fopen(newNumMetaFile, "r");
					
					if (fread((copyBuf+24),1,metaFileSize,numMetaFile) < 0)
					{
						//printf("Error in reading meta file\n");
					}
		//				("Meta Read \n%s\n\n\n\n",copyBuf);

					fclose(numMetaFile);


					/*****************************************************************/

					int sendMetaDataPacketLength =  metaFileSize + 24;
					filesize = filesize - sendMetaDataPacketLength;
					int intitalDataToBeSent = MAXFILEBUF - sendMetaDataPacketLength;
					if (fread((copyBuf+metaFileSize+24),1,intitalDataToBeSent,numDataFile) < 0)
					{
						//printf("Error in reading store file\n");
					}
					//send file metadata.
					int sendByte=0;
					if ((sendByte=send(socketDesc,&(copyBuf),MAXFILEBUF, 0)) == -1)
					{
						//printf("ERROR: error in sending  Data. from write Thread.\n\n");
						pthread_exit(NULL);
					}

					//printf("Data Read\n%s\n\n\n\n",copyBuf);
					//sending entire file.
					
					int numberOfSegments = ceil((double)filesize/MAXFILEBUF);	
			//		printf("BYTES SENT : %d\n",sendByte);
			//		printf("WRITE THREAD: Number of Segments is %d\n",numberOfSegments);
					int dataleft=filesize;
					if(dataleft<0)
					{
					}
				
					int remainingDataToBeCopied = filesize;
					// char copyBuf[MAXFILEBUF];
					 memset(&copyBuf[0],'\0',MAXFILEBUF);
					for(int k=0;k<numberOfSegments;k++)
					{
						int bytestoread;
						if (remainingDataToBeCopied > MAXFILEBUF)
						{
							bytestoread = MAXFILEBUF;
							remainingDataToBeCopied = remainingDataToBeCopied - MAXFILEBUF;
						}
						else
							bytestoread = remainingDataToBeCopied;

						memset(&copyBuf[0],'\0',MAXFILEBUF);
						if (fread(copyBuf,1,bytestoread,numDataFile) < 0)
						{
							//printf("Error in reading store file\n");
						}
						//fwrite(copyBuf, 1, bytestoread, numDataFile);	
						
						//send file data.

						////printf("%s\n\n\n\n",copyBuf);
						 memset(&copyBuf[0],'\0',MAXFILEBUF);
						if (send(socketDesc,copyBuf,bytestoread, 0) == -1)
						{
							//printf("ERROR: error in sending  Data. from write Thread.\n\n");
							pthread_exit(NULL);
						}
						//sleep(1);
					}
			//		printf("WRITE THREAD: FILE SENT\n");
					fclose(numDataFile);
					//fclose(sfile);

				}
			}
//=========================================================================================GET RESP OVER=============================





			else
			{
				if(itemFromQueue.msgHeader.msgDataLength!=0)
				{
		//			printf("Sent data for %x\n",itemFromQueue.msgHeader.messageType);
					if (send(socketDesc,&(itemFromQueue.dataBuf),itemFromQueue.msgHeader.msgDataLength, 0) == -1)
					{
						//printf("ERROR: error in sending  Data. from write Thread.\n\n");
						pthread_exit(NULL);
					}
				}
			}
			/*
			pthread_mutex_lock(&wQBitsetMutex);
						//printf("Acquire 1.\n");
						pthread_mutex_lock(&sockIndexMapMutex);
							//int index= findBitIndex();
							//printf("Acquire 2.\n");
							//if(terminate)
							//{
								wQueueIndexBitMap.set(0,index);
								sockFDToQIndexMap.erase(socketDesc);
								keepAliveTimers.erase(index);
								close(socketDesc);
							//}
							//printf("After reseting the maps.\n");
						pthread_mutex_unlock(&sockIndexMapMutex);
				pthread_mutex_unlock(&wQBitsetMutex);
			pthread_exit(NULL);
			*/	
		
		
		//printf("SENT msgtype%x==> %s to %d \n\n",itemFromQueue.msgHeader.messageType, itemFromQueue.dataBuf,socketDesc);
	}





	//char buff[]="Hi i am sending data...";
	//printf("\nsending buff : %s\n",buff);
	/*if (send(socketDesc,buff,sizeof(buff), 0) == -1)
	{
		printf("\nERROR: error in sending Hello Data.\n");
		//perror("error in sending Hello Data");
	}
	//sleep(5);
	*/
	pthread_exit(NULL);
}
